﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using TableTool.Model;



namespace TableTool
{
    public class KeyboardHook
    {
        public delegate int HookProc(int nCode, int wParam, IntPtr lParam);

        [StructLayout(LayoutKind.Sequential)]
        public class KeyboardHookStruct
        {
            public int vkCode;

            public int scanCode;

            public int flags;

            public int time;

            public int dwExtraInfo;
        }

        private static int hKeyboardHook;

        private static int hKeyResult;

        public const int WH_KEYBOARD_LL = 13;

        public HookProc KeyboardHookProcedure;

        private const int WM_KEYDOWN = 256;

        private const int WM_KEYUP = 257;

        private const int WM_SYSKEYDOWN = 260;

        private const int WM_SYSKEYUP = 261;

        public event KeyEventHandler KeyDownEvent;

        public event KeyPressEventHandler KeyPressEvent;

        public event KeyEventHandler KeyUpEvent;

        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        public static extern bool UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        private static extern int GetCurrentThreadId();

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

        [DllImport("user32")]
        public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState);

        [DllImport("user32")]
        public static extern int GetKeyboardState(byte[] pbKeyState);

        [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
        private static extern short GetKeyState(int vKey);
        /// <summary>
        /// 
        /// </summary>
        public KeyDownCloseModel model { get; set; }

        public bool OpenFlag1 { get; set; }
        public bool OpenFlag2 { get; set; }
        public bool OpenFlag3 { get; set; }
        public void Start()
        {
            if (hKeyboardHook == 0)
            {
                KeyboardHookProcedure = KeyboardHookProc;
                hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
                SetWindowsHookEx(13, KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());
                if (hKeyboardHook == 0)
                {
                    Stop();
                    throw new Exception("安装键盘钩子失败");
                }
            }
        }

        public void Stop()
        {
            bool flag = true;
            if (hKeyboardHook != 0)
            {
                flag = UnhookWindowsHookEx(hKeyboardHook);
                hKeyboardHook = 0;
            }
            if (!flag)
            {
                throw new Exception("卸载钩子失败！");
            }
        }


        private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
        {
            Console.WriteLine("KeyboardHookProc"+nCode);
            int hKeyResult = 0;
            List<int> list = new List<int>();
            if (nCode >= 0 && (this.KeyDownEvent != null || this.KeyUpEvent != null || this.KeyPressEvent != null))
            {
                KeyboardHookStruct keyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                if (this.KeyDownEvent != null && (wParam == 256 || wParam == 260))
                {
                    Keys vkCode = (Keys)keyboardHookStruct.vkCode;
                    KeyEventArgs e = new KeyEventArgs(vkCode);
                    if (OpenFlag1)
                    {
                        if (model.P1.Contains(e.KeyData))
                        {
                            hKeyResult = 1;
                        }
                    }
                    if (OpenFlag2)
                    {
                        if (model.P2.Contains(e.KeyData))
                        {
                            hKeyResult = 1;
                        }
                    }
                    if (OpenFlag3)
                    {
                        if (model.P3.Contains(e.KeyData))
                        {
                            hKeyResult = 1;
                        }
                    }
                    this.KeyDownEvent(this, e);
                }
            }
            return hKeyResult;
        }
    }
}